/**
 * @file    woshsrv.cpp
 * @brief   WOSH Server [woshsrv], Multiplatform.
 *
 *          Initialize wosh::WoshKernel and configuration, dynamic allocators,
 *          open a local shell (mostly for debugging/testing).
 *
 *          Tested with:
 *            - Microsoft Visual Studio 2008, QT 4.5 for Windows32
 *            - GCC 4.1, QT 4.4
 *
 *
 ****************************************************************************
 * \section page_applications_woshsrv WOSH Server [Multiplatform]
 *
 * WOSH Server is the core application of WOSH Framework.
 *
 * Console Application. By default, it writes logs on stdout.
 *
 * Here are some screenshots:
 * \image html extras/screenshots/WOSH.woshsrv.bundle-listing.png "woshsrv"
 * \image html extras/screenshots/WOSH.woshsrv.x10-automation-player.png "woshsrv"
 *
 *
 ****************************************************************************
 * @version $Id: woshsrv.cpp 2877 2010-08-09 00:02:53Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/

//////////////////////////////////////////////////////////////////
#define _CONFIG_FILE		"../etc/wosh/wosh.conf"
#define _LOG_FILE			"../var/log/woshsrv.log"
//////////////////////////////////////////////////////////////////

#include <core/WoshKernel.h>
#include <core/ObjectFactory.h>
#include <core/BundleManager.h>
#include <core/SessionManager.h>
#include <core/LogHandlers.h>

#include <QCoreApplication>
//////////////////////////////////////////////////////////////////
using namespace std;
using namespace wosh;
using namespace wosh::application;
//////////////////////////////////////////////////////////////////
#ifdef _OS_POSIX
  void woshsrv_signal_handler( int sig );
  void woshsrv_registerSignals();
#endif
//////////////////////////////////////////////////////////////////

int main(int argc, char **argv)
 {
	QCoreApplication app( argc, argv );
#ifdef _OS_POSIX
	woshsrv_registerSignals();
#endif

	//////////////////////////////////////////////////////////////////////////////////////
	// setup defauld Log-handler
	DefaultSharedLogHandler::getInstance()->setFileName( _LOG_FILE );
	DefaultSharedLogHandler::getInstance()->setStdOut(true, true);

	//////////////////////////////////////////////////////////////////////////////////////
	// load settings for command line arguments, default configuration file and folders
	// WOSH configuration architecture is similar to Apache2
	Settings* woshSettings = new Settings();
	woshSettings->loadFromArgs(argc, argv);

	std::string cfgFile = woshSettings->getValueOf( "", "ConfigFile", _CONFIG_FILE ).toString();
	WRESULT loaded = woshSettings->loadConfigurationFile( cfgFile );
	if ( loaded != WRET_OK ) {
		printf("WOSH CRITICAL ERROR #%i\n", loaded );
		printf(" Configuration is  file missing or invalid: %s\n", cfgFile.c_str() );
		printf(" Default configuration file is /etc/wosh/wosh.conf, a sample configuration file is provided (/etc/wosh/wosh.default.conf)\n" );
		printf(" Refer to http://wosh.sourceforge.net/doc/page_config.html\n" );
		return 1;
	 }
	std::string woshName = woshSettings->getValueOf( "WoshKernel", "Name", "" ).toString();

	//////////////////////////////////////////////////////////////////////////////////////
	// alloc Kernel
	WoshKernel core( woshName, woshSettings );

	//////////////////////////////////////////////////////////////////////////////////////
	// now we installed and configured all CORE modules, we can init kernel (them)
	// (so bundles will be loaded, if autoload is set)
	core.init();

	//////////////////////////////////////////////////////////////////////////////////////
	// enter loop (acquire thread), it will set kernel-state to running
	// (so bundles will start, if autostart is set)
	core.start();

	//////////////////////////////////////////////////////////////////////////////////////
	// open a local shell
	Session* sessionConsole = ObjectFactory::createTypeOf<Session>("wosh::communication::SessionShell", 0.0);
	if ( sessionConsole == NULL ) {
		printf("WOSH WARNING\n" );
		printf(" Cannot create Session of type %s\n", "wosh::communication::SessionShell" );
		printf(" continuing (without local console)\n" );
	 }
	else {
		core.sessions().registerSession( sessionConsole );
		sessionConsole->open();
	 }

	//////////////////////////////////////////////////////////////////////////////////////
	// enter loop (acquire thread), it will set kernel-state to running
	core.enterLoop();

	//////////////////////////////////////////////////////////////////////////////////////
	// save settings
	// what? how?

	//////////////////////////////////////////////////////////////////////////////////////
	return 0;
 }


//////////////////////////////////////////////////////////////////
#ifdef _OS_POSIX
 #include <fcntl.h>
 #include <unistd.h>
 #include <signal.h>

void woshsrv_signal_handler( int sig ) {
	switch(sig) {
		case SIGHUP:
		case SIGTERM:
		case SIGINT: {
			printf("======================== Interrupt signal caught\n");
			ASSERT( WoshKernel::getInstance() != NULL )
			WoshKernel::getInstance()->shutdown();
			break;
		 }
	}
 }

void woshsrv_registerSignals() {
	signal(SIGINT, woshsrv_signal_handler);
	signal(SIGTERM, woshsrv_signal_handler);
	signal(SIGHUP, woshsrv_signal_handler);
 }
#endif
//////////////////////////////////////////////////////////////////
